home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-10 | 26.3 KB | 965 lines | [TEXT/PJMM] |
- unit WELineLayout;
-
- { WASTE PROJECT: }
- { Line Layout, Creation & Destruction, Getting and Setting Variables, etc. }
-
- { Copyright © 1993-1994 Marco Piovanelli }
- { All Rights Reserved }
-
- interface
- uses
- WEDrawing;
-
- function WENew (var destRect, viewRect: LongRect;
- flags: Integer;
- var hWE: WEHandle): OSErr;
- procedure WEDispose (hWE: WEHandle);
- procedure WEStopInlineSession (hWE: WEHandle);
- function _WERemoveLine (lineIndex: LongInt;
- pWE: WEPtr): OSErr;
- function _WERecalBreaks (var startLine, endLine: LongInt;
- hWE: WEHandle): OSErr;
- procedure _WERecalSlops (firstLine, lastLine: LongInt;
- hWE: WEHandle);
- function WECalText (hWE: WEHandle): OSErr;
- function WEGetTextLength (hWE: WEHandle): LongInt;
- function WECountLines (hWE: WEHandle): LongInt;
- function WEGetHeight (startLine, endLine: LongInt;
- hWE: WEHandle): LongInt;
- procedure WEGetSelection (var selStart, selEnd: LongInt;
- hWE: WEHandle);
- procedure WEGetDestRect (var destRect: LongRect;
- hWE: WEHandle);
- procedure WESetDestRect (var destRect: LongRect;
- hWE: WEHandle);
- procedure WEGetViewRect (var viewRect: LongRect;
- hWE: WEHandle);
- procedure WESetViewRect (var viewRect: LongRect;
- hWE: WEHandle);
- function WEGetText (hWE: WEHandle): Handle;
- function WEGetChar (offset: LongInt;
- hWE: WEHandle): Char;
- function WEGetAlignment (hWE: WEHandle): SignedByte;
- function WEFeatureFlag (feature: Integer;
- action: Integer;
- hWE: WEHandle): Integer;
- function WEUseText (text: Handle;
- hWE: WEHandle): OSErr;
- function WEGetInfo (selector: OSType;
- info: Ptr;
- hWE: WEHandle): OSErr;
- function WESetInfo (selector: OSType;
- info: Ptr;
- hWE: WEHandle): OSErr;
-
- implementation
- uses
- Drag, FixMath, QDOffscreen, TextServices;
-
- function _WERegisterWithTSM (hWE: WEHandle): OSErr;
-
- { the WE record must be already locked }
-
- label
- 1;
- var
- pWE: WEPtr;
- typeList: InterfaceTypeList;
- err: OSErr;
- begin
- pWE := hWE^;
-
- { do nothing if the Text Services Manager isn't available }
- if BTST(pWE^.flags, weFHasTextServices) then
- begin
- typeList[0] := kTextService;
- err := NewTSMDocument(1, typeList, pWE^.tsmReference, LongInt(hWE));
- if (err <> noErr) then
-
- { we don't consider it an error if our client application isn't TSM-aware }
- if (err <> tsmNeverRegisteredErr) then
- goto 1;
- end;
-
- { clear result code }
- err := noErr;
-
- 1:
- { return result code }
- _WERegisterWithTSM := err;
-
- end; { _WERegisterWithTSM }
-
- procedure WEStopInlineSession (hWE: WEHandle);
- var
- tsmReference: TSMDocumentID;
- begin
- tsmReference := hWE^^.tsmReference;
- if (tsmReference <> nil) then
- IgnoreShort(FixTSMDocument(tsmReference));
- end; { WEStopInlineSession }
-
- function WENew (var destRect, viewRect: LongRect;
- flags: Integer;
- var hWE: WEHandle): OSErr;
- label
- 1, 2;
- var
- pWE: WEPtr;
- allocFlags: Integer;
- weFlags: LongInt;
- response: LongInt;
- r: Rect;
- err: OSErr;
- begin
- pWE := nil;
- weFlags := flags;
- allocFlags := kAllocClear;
-
- { allocate the WE record }
- err := _WEAllocate(SizeOf(WERec), allocFlags, hWE);
- if (err <> noErr) then
- goto 1;
-
- { lock it down }
- HLock(Handle(hWE));
- pWE := hWE^;
-
- { get active port }
- GetPort(pWE^.port);
-
- { determine whether temporary memory should be used for data structures }
- if BTST(weFlags, weFUseTempMem) then
- allocFlags := allocFlags + kAllocTemp;
-
- { allocate the text handle (initially empty) }
- err := _WEAllocate(0, allocFlags, pWE^.hText);
- if (err <> noErr) then
- goto 1;
-
- { allocate the line array }
- err := _WEAllocate(2 * SizeOf(LineRec), allocFlags, pWE^.hLines);
- if (err <> noErr) then
- goto 1;
-
- { allocate the style table }
- err := _WEAllocate(SizeOf(StyleTableElement), allocFlags, pWE^.hStyles);
- if (err <> noErr) then
- goto 1;
-
- { allocate the run array }
- err := _WEAllocate(2 * SizeOf(RunArrayElement), allocFlags, pWE^.hRuns);
- if (err <> noErr) then
- goto 1;
-
- { check for the presence of various system software features }
- { determine whether Color QuickDraw is available }
- if (%_Gestalt(gestaltQuickDrawVersion, response) = noErr) then
- if (response >= gestalt8BitQD) then
- BSET(weFlags, weFHasColorQD);
-
- { determine whether the Text Services manager is available }
- if (%_Gestalt(gestaltTSMgrVersion, response) = noErr) then
- BSET(weFlags, weFHasTextServices);
-
- { determine if there are any non-Roman scripts enabled }
- if (GetEnvirons(smEnabled) > 1) then
- BSET(weFlags, weFNonRoman);
-
- { determine whether a double-byte script is installed }
- if (GetEnvirons(smDoubleByte) <> 0) then
- BSET(weFlags, weFDoubleByte);
-
- { determine whether the Drag Manager is available }
- if (%_Gestalt(gestaltDragMgrAttr, response) = noErr) then
- if BTST(response, gestaltDragMgrPresent) then
- BSET(weFlags, weFDragAndDrop);
-
- { initialize miscellaneous fields of the WE record }
- pWE^.nLines := 1;
- pWE^.nStyles := 1;
- pWE^.nRuns := 1;
- pWE^.viewRect := viewRect;
- pWE^.destRect := destRect;
- pWE^.flags := weFlags;
- pWE^.tsmAreaStart := kInvalidOffset;
- pWE^.tsmAreaEnd := kInvalidOffset;
- pWE^.dragCaretOffset := kInvalidOffset;
-
- { create a region to hold the view rectangle }
- pWE^.viewRgn := NewRgn;
- WELongRectToRect(viewRect, r);
- RectRgn(pWE^.viewRgn, r);
-
- { initialize the style run array }
- with pWE^.hRuns^^[1] do
- begin
- runStart := 1;
- styleIndex := -1;
- end;
-
- { initialize the style table }
- with pWE^.hStyles^^[0] do
- begin
- refCount := 1;
-
- { copy text attributes from the active graphics port }
- info.runStyle.tsFont := pWE^.port^.txFont;
- info.runStyle.tsSize := pWE^.port^.txSize;
- info.runStyle.tsFace := GrafPtr1(pWE^.port)^.txFace;
- if BTST(weFlags, weFHasColorQD) then
- GetForeColor(info.runStyle.tsColor);
- _WEFillFontInfo(pWE^.port, info);
-
- end;
-
- { initialize the line array }
- err := WECalText(hWE);
- if (err <> noErr) then
- goto 1;
-
- { register with the Text Services Manager }
- err := _WERegisterWithTSM(hWE);
- if (err <> noErr) then
- goto 1;
-
- { unlock the WE record }
- HUnlock(Handle(hWE));
-
- { clear result code }
- err := noErr;
-
- { skip clean-up section }
- goto 2;
-
- 1:
- { clean up }
- if (pWE <> nil) then
- begin
- _WEForgetHandle(pWE^.hText);
- _WEForgetHandle(pWE^.hLines);
- _WEForgetHandle(pWE^.hStyles);
- _WEForgetHandle(pWE^.hRuns);
- if (pWE^.viewRgn <> nil) then
- DisposeRgn(pWE^.viewRgn);
- end;
- _WEForgetHandle(hWE);
-
- 2:
- { return result code }
- WENew := err;
-
- end; { WENew }
-
- (*** WEDispose needs to destroy the action stack (aka the Undo buffer), ***)
- (*** but unfortunately, WEClearUndo() is defined in a subsequent unit, ***)
- (*** so I've temporarily added this ugly external declaration ***)
-
- procedure WEClearUndo (hWE: WEHandle);
- external;
-
- procedure WEDispose (hWE: WEHandle);
- var
- pWE: WEPtr;
- pTable: StyleTablePtr;
- index: LongInt;
- begin
-
- { sanity check: make sure WE isn't NIL }
- if (hWE = nil) then
- Exit(WEDispose);
-
- { lock the WE record }
- HLock(Handle(hWE));
- pWE := hWE^;
-
- { clear the Undo buffer }
- WEClearUndo(hWE);
-
- { unregister with the Text Services Manager }
- if (pWE^.tsmReference <> nil) then
- begin
- IgnoreShort(DeleteTSMDocument(pWE^.tsmReference));
- pWE^.tsmReference := nil;
- end;
-
- { dispose of the offscreen graphics world }
- if (pWE^.offscreenPort <> nil) then
- begin
- DisposeGWorld(GWorldPtr(pWE^.offscreenPort));
- pWE^.offscreenPort := nil;
- end;
-
- if (pWE^.hStyles <> nil) then
- begin
-
- { lock the style table }
- HLock(Handle(pWE^.hStyles));
- pTable := pWE^.hStyles^;
-
- { walk the style table, disposing of all embedded objects referenced there }
- index := 0;
- while (index < pWE^.nStyles) do
- with pTable^[index] do
- begin
- if (refCount > 0) then
- if (_WEFreeObject(WEObjectDescHandle(info.runStyle.tsObject)) <> noErr) then
- ; { don't known what to do with errors }
- index := index + 1;
- end;
- end;
-
- { dispose of auxiliary data structures }
- _WEForgetHandle(pWE^.hText);
- _WEForgetHandle(pWE^.hLines);
- _WEForgetHandle(pWE^.hStyles);
- _WEForgetHandle(pWE^.hRuns);
- DisposeRgn(pWE^.viewRgn);
-
- { dispose of the WE record }
- DisposeHandle(Handle(hWE));
-
- end; { WEDispose }
-
- function _WERemoveLine (lineIndex: LongInt;
- pWE: WEPtr): OSErr;
-
- { remove the specified element from the line array }
-
- begin
-
- { do the removal (errors returned by _WERemoveSlot can be safely ignored) }
- _WERemoveLine := _WERemoveSlot(pWE^.hLines, lineIndex, SizeOf(LineRec));
-
- { decrement line count }
- pWE^.nLines := pWE^.nLines - 1;
-
- end; { _WERemoveLine }
-
- function InsertLine (lineIndex: LongInt;
- var theLine: LineRec;
- pWE: WEPtr): OSErr;
-
- { insert the specified element in the line array }
-
- var
- err: OSErr;
- begin
- InsertLine := noErr;
-
- { do the insertion }
- err := _WEInsertSlot(pWE^.hLines, @theLine, lineIndex, SizeOf(theLine));
- if (err <> noErr) then
- begin
- InsertLine := err;
- Exit(InsertLine);
- end;
-
- { increment line count }
- pWE^.nLines := pWE^.nLines + 1;
-
- end; { InsertLine }
-
- procedure _WEBumpOrigin (lineIndex: LongInt;
- deltaOrigin: LongInt;
- pWE: WEPtr);
- var
- pOrigin: LongIntPtr;
- nLines: LongInt;
- begin
- pOrigin := @pWE^.hLines^^[lineIndex].lineOrigin;
-
- { loop through the line run array adjusting the lineOrigin fields }
- nLines := pWE^.nLines;
- while (lineIndex <= nLines) do
- begin
- pOrigin^ := pOrigin^ + deltaOrigin;
- pOrigin := LongIntPtr(LongInt(pOrigin) + SizeOf(LineRec));
- lineIndex := lineIndex + 1;
- end;
- end; { _WEBumpOrigin }
-
- function _WEFindLineBreak (lineStart: LongInt;
- hWE: WEHandle): LongInt;
-
- { Find where to break the line beginning at lineStart }
- { the WE record and the text must be already locked }
- { the current graphics port must be already set up correctly }
-
- var
- pWE: WEPtr;
- pText: Ptr;
- offset, breakOffset: LongInt;
- textLength: LongInt;
- remainingLength: LongInt;
- segmentStart, segmentEnd: LongInt;
- runIndex: LongInt;
- runInfo: WERunInfo;
- pixelWidth: Fixed;
- script, previousScript: ScriptCode;
- isBreak: Boolean;
- begin
- pWE := hWE^;
- offset := lineStart;
- pText := Ptr(LongInt(pWE^.hText^) + offset);
- remainingLength := pWE^.textLength - offset;
-
- { find the style run index corresponding to the first segment on this line }
- runIndex := _WEOffsetToRun(offset, hWE);
-
- { initialize pixelWidth to the width of the destination rectangle, as a Fixed quantity }
- pixelWidth := BSL(pWE^.destRect.right - pWE^.destRect.left, 16);
-
- { STYLE SEGMENT LOOP }
- repeat
-
- { get style run information for the current style run }
- _WEGetIndStyle(runIndex, runInfo, hWE);
- runIndex := runIndex + 1;
-
- { set text attributes in the graphics port }
- TextFont(runInfo.runAttrs.runStyle.tsFont);
- %_TextFace(runInfo.runAttrs.runStyle.tsFace);
- TextSize(runInfo.runAttrs.runStyle.tsSize);
-
- { if we're handling multiscript text, keep track of script boundaries }
- if BTST(pWE^.flags, weFNonRoman) then
- begin
-
- { what is the script for this segment? }
- script := Font2Script(runInfo.runAttrs.runStyle.tsFont);
-
- { have we crossed a script run boundary in the middle of a line? }
- if (runInfo.runStart > offset) and (script <> previousScript) then
- begin
-
- { leave behind the all previous segments on this line }
- offset := runInfo.runStart;
- pText := Ptr(LongInt(pWE^.hText^) + offset);
- remainingLength := pWE^.textLength - offset;
- end;
-
- previousScript := script;
- end; { if non-Roman }
-
- { we'll pass textLength as the second parameter to StyledLineBreak }
- { although this parameter is declared as a long, StyledLineBreak uses only }
- { the low word, so make sure it doesn't trespass the 32,767 byte threshold! }
- textLength := _WEPinInRange(remainingLength, 0, maxint);
-
- { calculate segmentStart and segmentEnd relative to offset }
- segmentStart := _WEPinInRange(runInfo.runStart - offset, 0, textLength);
- segmentEnd := _WEPinInRange(runInfo.runEnd - offset, 0, textLength);
-
- { set breakOffset to a non-zero value for the first script run on the line, }
- { set it to zero for all subsequent script runs }
- breakOffset := Integer(offset = lineStart);
-
- if (runInfo.runAttrs.runStyle.tsObject <> kNullObject) then
- begin
-
- { EMBEDDED OBJECT }
- { subtract object width from pixelWidth }
- pixelWidth := pixelWidth - BSL(WEObjectDescHandle(runInfo.runAttrs.runStyle.tsObject)^^.objectSize.h, 16);
-
- { stop looping if pixelWidth has gone negative }
- isBreak := (pixelWidth < 0);
-
- if (isBreak) then
- breakOffset := segmentStart { break line before the object }
- else
- breakOffset := segmentEnd; { break line after the object }
-
- end
- else
- begin
-
- { REGULAR TEXT }
- { StyledLineBreak does the work for us }
- isBreak := (StyledLineBreak(pText, textLength, segmentStart, segmentEnd, 0, pixelWidth, breakOffset) <> smBreakOverflow);
-
- end;
-
- { break the line anyway when we reach the end of the text }
- if (segmentEnd >= remainingLength) then
- isBreak := true;
-
- until (isBreak);
-
- { return the offset from lineStart to the break point }
- _WEFindLineBreak := (offset - lineStart) + breakOffset;
-
- end; { _WEFindLineBreak }
-
- procedure _WECalcHeights (rangeStart, rangeEnd: LongInt;
- var lineAscent, lineDescent: Integer;
- hWE: WEHandle);
-
- { Find the maximum ascent and descent values between rangeStart and rangeEnd }
- { the WE record must be already locked }
- { the current graphics port must be already set up correctly }
-
- var
- runIndex: LongInt;
- runInfo: WERunInfo;
- runAscent, runDescent: Integer;
- begin
- lineAscent := 1;
- lineDescent := 1;
-
- { find the style run index corresponding to the first segment on this line }
- runIndex := _WEOffsetToRun(rangeStart, hWE);
-
- { STYLE SEGMENT LOOP }
- repeat
-
- { get style run information for the current style run }
- _WEGetIndStyle(runIndex, runInfo, hWE);
- runIndex := runIndex + 1;
-
- { calculate ascent and descent (actually, descent + leading) values for this style run }
- if (runInfo.runAttrs.runStyle.tsObject <> kNullObject) then
- begin
-
- { EMBEDDED OBJECT }
- runAscent := WEObjectDescHandle(runInfo.runAttrs.runStyle.tsObject)^^.objectSize.v;
- runDescent := 0;
- end
- else
- begin
-
- { REGULAR TEXT }
- runAscent := runInfo.runAttrs.runAscent;
- runDescent := runInfo.runAttrs.runHeight - runAscent;
- end;
-
- { save the maximum values in lineAscent and lineDescent }
- if (runAscent > lineAscent) then
- lineAscent := runAscent;
- if (runDescent > lineDescent) then
- lineDescent := runDescent;
-
- { keep looping until we reach rangeEnd }
- until (runInfo.runEnd >= rangeEnd);
-
- end; { _WECalcHeights }
-
- function _WERecalBreaks (var startLine, endLine: LongInt;
- hWE: WEHandle): OSErr;
-
- { Recalculates line breaks, line heights and ascents for all the text or for a portion of it. }
- { On entry, startLine and endLine define a range of lines to recalculate. }
- { On exit, startLine to endLine defines the range of lines actually recalculated }
- { the WE record must already be locked }
-
- label
- 1;
- var
- pWE: WEPtr;
- pLine: LinePtr;
- lineInfo, oldLineInfo: LineRec;
- lineIndex: LongInt;
- recalThreshold: LongInt;
- lineOffset: LongInt;
- lineAscent, lineDescent: Integer;
- saveTextLock: Boolean;
- saveEnvironment: QDEnvironment;
- err: OSErr;
- begin
- _WERecalBreaks := noErr;
- pWE := hWE^;
-
- { lock the text }
- saveTextLock := _WESetHandleLock(pWE^.hText, true);
-
- { find the character offset that must be necessarily reached before we can }
- { even consider the possibility of stopping the recalculation process }
- { this offset, recalThreshold, is the last character on endLine _before_ recalculation }
- lineIndex := _WEPinInRange(endLine, 0, pWE^.nLines - 1);
- recalThreshold := pWE^.hLines^^[lineIndex + 1].lineStart;
-
- { we start recalculating line breaks from the line actually _preceding_ startLine, }
- { since editing startLine may cause part of its text to fit on the preceding line }
- lineIndex := _WEPinInRange(startLine - 1, 0, pWE^.nLines - 1);
-
- { find where in the text recalculation should begin }
- lineInfo := pWE^.hLines^^[lineIndex];
-
- { save the QuickDraw environment }
- _WESaveQDEnvironment(pWE^.port, false, saveEnvironment);
-
- { MAIN LINE BREAKING LOOP }
- repeat
-
- { find where to break the current line }
- lineOffset := _WEFindLineBreak(lineInfo.lineStart, hWE);
-
- { make sure we advance at least by one character (unless we reached the end of text) }
- if (lineOffset <= 0) then
- if (lineInfo.lineStart < pWE^.textLength) then
- lineOffset := 1;
-
- { calculate ascent and descent values for this line }
- _WECalcHeights(lineInfo.lineStart, lineInfo.lineStart + lineOffset, lineAscent, lineDescent, hWE);
-
- { save the maximum line ascent for this line in the line array }
- pLine := @pWE^.hLines^^[lineIndex];
- pLine^.lineAscent := lineAscent;
-
- { increment counters (go to the next line array entry) }
- lineIndex := lineIndex + 1;
- lineInfo.lineStart := lineInfo.lineStart + lineOffset;
- lineInfo.lineOrigin := lineInfo.lineOrigin + (lineAscent + lineDescent);
- pLine := LinePtr(LongInt(pLine) + SizeOf(LineRec));
-
- { compare the newly calculated line start with the old value }
- { if the new line start comes before the old line start, insert a new element }
- oldLineInfo := pLine^;
- if (lineIndex > pWE^.nLines) | (lineInfo.lineStart < oldLineInfo.lineStart) then
- begin
- err := InsertLine(lineIndex, lineInfo, pWE);
-
- { clean up and exit if we ran out of memory }
- if (err <> noErr) then
- begin
- _WERecalBreaks := err;
- goto 1;
- end;
- end
- else
- begin
-
- { overwrite the old element }
- pLine^.lineStart := lineInfo.lineStart;
- pLine^.lineOrigin := lineInfo.lineOrigin;
-
- { remove all further elements which have a lineStart field }
- { less than or equal to the current one }
- while (lineIndex + 1 <= pWE^.nLines) & (lineInfo.lineStart >= pWE^.hLines^^[lineIndex + 1].lineStart) do
- err := _WERemoveLine(lineIndex + 1, pWE);
-
- { if the new line start is the same as the old one... }
- if (lineInfo.lineStart = oldLineInfo.lineStart) then
- begin
-
- { ...and recalThreshold has been reached, we can stop recalculating line breaks }
- if (lineInfo.lineStart >= recalThreshold) then
- begin
- { although line breaks need not be changed from lineIndex on, }
- { the lineOrigin fields may need to be changed }
- if (lineInfo.lineOrigin <> oldLineInfo.lineOrigin) then
- _WEBumpOrigin(lineIndex + 1, lineInfo.lineOrigin - oldLineInfo.lineOrigin, pWE);
-
- { exit from the line breaking loop }
- goto 1;
- end;
- end
- else
- begin
-
- { otherwise, the new line start comes after the old line start... }
- { if the current line is the one preceding startLine, warn our caller about this }
- if ((lineIndex > 0) and (lineIndex = startLine)) then
- startLine := lineIndex - 1;
-
- end;
- end;
-
- until (lineInfo.lineStart >= pWE^.textLength);
-
- 1:
- { set destRect.bottom to destRect.top + total text height }
- pWE^.destRect.bottom := pWE^.destRect.top + WEGetHeight(0, pWE^.nLines, hWE);
-
- { quirk: if the last character in the text is a carriage return, the caret appears }
- { below the last line, so in this case we need to add the extra height to destRect.bottom }
- if (WEGetChar(pWE^.textLength - 1, hWE) = CHR(13)) then
- pWE^.destRect.bottom := pWE^.destRect.bottom + WEGetHeight(pWE^.nLines - 1, pWE^.nLines, hWE);
-
- { return through endLine the index of the last line affected by recalculation }
- endLine := lineIndex - 1;
-
- { make sure startLine isn't greater than endLine }
- if (startLine > endLine) then
- startLine := endLine;
-
- { unlock the text }
- IgnoreBoolean(_WESetHandleLock(pWE^.hText, saveTextLock));
-
- { restore the QuickDraw environment }
- _WERestoreQDEnvironment(saveEnvironment);
-
- end; { _WERecalBreaks }
-
- procedure _WERecalSlops (firstLine, lastLine: LongInt;
- hWE: WEHandle);
-
- { Calculates the lineSlop and lineJustAmount fields }
- { of the line array for the specified lines }
-
- var
- pWE: WEPtr;
- textLength: LongInt;
- totalSlop, lineWidth: Integer;
- totalProportion: Fixed;
-
- function SLCalcSlop (pLine: LinePtr;
- pAttrs: WERunAttributesPtr;
- pSegment: Ptr;
- segmentStart, segmentLength: LongInt;
- styleRunPosition: JustStyleCode): Boolean;
- var
- segmentWidth: Integer;
- segmentProportion: Fixed;
- isEndOfLine: Boolean;
- begin
- SLCalcSlop := false; { keep looping }
-
- { see if this text segment ends with a carriage return, or if we've reached the }
- { end of the text (in which case we don't want any justification to take place) }
- isEndOfLine := (segmentStart + segmentLength >= textLength) | (Ptr(LongInt(pSegment) + segmentLength - 1)^ = kEOL);
-
- { if this is the first segment on the line, reset line totals }
- if (styleRunPosition <= smLeftStyleRun) then
- begin
- totalSlop := lineWidth;
- totalProportion := 0;
- end;
-
- if (pAttrs^.runStyle.tsObject <> kNullObject) then
- begin
-
- { EMBEDDED OBJECT }
- { segment width is just object width; no extra space can be applied for justification }
- segmentWidth := WEObjectDescHandle(pAttrs^.runStyle.tsObject)^^.objectSize.h;
- segmentProportion := 0;
- end
- else
- begin
-
- { REGULAR TEXT }
- { if this is the last segment on the line, strip trailing spaces }
- if (not Odd(styleRunPosition)) then
- segmentLength := VisibleLength(pSegment, segmentLength);
-
- { measure this segment }
- segmentWidth := TextWidth(pSegment, 0, segmentLength);
-
- { calculate the proportion of extra space to apply to this text segment }
- segmentProportion := NPortionText(pSegment, segmentLength, styleRunPosition, Point(kOneToOneScaling), Point(kOneToOneScaling));
- end;
-
- { keep track of line totals }
- totalSlop := totalSlop - segmentWidth;
- totalProportion := totalProportion + segmentProportion;
-
- { if this is the last segment on the line, save values in the line array }
- if (not Odd(styleRunPosition)) then
- begin
-
- { make sure slop is non-negative }
- if (totalSlop < 0) then
- totalSlop := 0;
- pLine^.lineSlop := totalSlop;
-
- if (isEndOfLine) then
- pLine^.lineJustAmount := 0
- else
- pLine^.lineJustAmount := FixDiv(BSL(totalSlop, 16), totalProportion);
-
- end;
- end; { SLCalcSlop }
-
- begin
- pWE := hWE^;
- textLength := pWE^.textLength;
- lineWidth := pWE^.destRect.right - pWE^.destRect.left;
-
- { calculate slop and normalized slop proportion for all lines }
- _WESegmentLoop(firstLine, lastLine, SLCalcSlop, hWE);
-
- end; { _WERecalSlops }
-
- function WECalText (hWE: WEHandle): OSErr;
- var
- startLine, endLine: LongInt;
- saveWELock: Boolean;
- err: OSErr;
- begin
-
- { lock WE record }
- saveWELock := _WESetHandleLock(hWE, true);
-
- { recalculate all line breaks }
- startLine := 0;
- endLine := maxLongInt;
- err := _WERecalBreaks(startLine, endLine, hWE);
-
- { recalculate line slops }
- if (err = noErr) then
- _WERecalSlops(startLine, endLine, hWE);
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- { return result code }
- WECalText := err;
-
- end; { WECalText }
-
- function WEUseText (text: Handle;
- hWE: WEHandle): OSErr;
- var
- pWE: WEPtr;
- textLength: LongInt;
- saveWELock: Boolean;
- begin
- WEUseText := noErr;
-
- { lock the WE record }
- saveWELock := _WESetHandleLock(hWE, true);
- pWE := hWE^;
-
- { install the text }
- _WEForgetHandle(pWE^.hText);
- pWE^.hText := text;
- textLength := %_GetHandleSize(text);
- pWE^.textLength := textLength;
- pWE^.hRuns^^[pWE^.nRuns].runStart := textLength + 1;
- pWE^.hLines^^[pWE^.nLines].lineStart := textLength;
-
- { unlock the WE record }
- IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
-
- end; { WEUseText }
-
- function WEGetAlignment (hWE: WEHandle): SignedByte;
- begin
- WEGetAlignment := hWE^^.alignment;
- end; { WEGetAlignment }
-
- procedure WEGetSelection (var selStart, selEnd: LongInt;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- begin
- pWE := hWE^;
- selStart := pWE^.selStart;
- selEnd := pWE^.selEnd;
- end; { WEGetSelection }
-
- procedure WESetDestRect (var destRect: LongRect;
- hWE: WEHandle);
- begin
- hWE^^.destRect := destRect;
- end; { WESetDestRect }
-
- procedure WEGetDestRect (var destRect: LongRect;
- hWE: WEHandle);
- begin
- destRect := hWE^^.destRect;
- end; { WEGetDestRect }
-
- procedure WESetViewRect (var viewRect: LongRect;
- hWE: WEHandle);
- var
- pWE: WEPtr;
- r: Rect;
- begin
- pWE := hWE^;
- pWE^.viewRect := viewRect;
-
- { keep the viewRgn in sync with the view rectangle }
- WELongRectToRect(viewRect, r);
- RectRgn(pWE^.viewRgn, r);
-
- end; { WESetViewRect }
-
- procedure WEGetViewRect (var viewRect: LongRect;
- hWE: WEHandle);
- begin
- viewRect := hWE^^.viewRect;
- end; { WEGetViewRect }
-
- function WEGetTextLength (hWE: WEHandle): LongInt;
- begin
- WEGetTextLength := hWE^^.textLength;
- end; { WEGetTextLength }
-
- function WECountLines (hWE: WEHandle): LongInt;
- begin
- WECountLines := hWE^^.nLines;
- end; { WECountLines }
-
- function WEGetHeight (startLine, endLine: LongInt;
- hWE: WEHandle): LongInt;
- var
- pWE: WEPtr;
- pLines: LineArrayPtr;
- nLines: LongInt;
- begin
- pWE := hWE^;
- pLines := pWE^.hLines^;
- nLines := pWE^.nLines;
- startLine := _WEPinInRange(startLine, 0, nLines);
- endLine := _WEPinInRange(endLine, 0, nLines);
- _WEReorder(startLine, endLine);
- WEGetHeight := pLines^[endLine].lineOrigin - pLines^[startLine].lineOrigin;
- end; { WEGetHeight }
-
- function WEGetText (hWE: WEHandle): Handle;
- begin
- WEGetText := hWE^^.hText;
- end; { WEGetText }
-
- function WEGetChar (offset: LongInt;
- hWE: WEHandle): Char;
- var
- pWE: WEPtr;
- begin
- WEGetChar := Char(0);
- pWE := hWE^;
-
- { sanity check: make sure offset is withing allowed bounds }
- if ((offset < 0) or (offset >= pWE^.textLength)) then
- Exit(WEGetChar);
-
- { get the specified character (actually, byte) }
- WEGetChar := WECharsHandle(pWE^.hText)^^[offset];
-
- end; { WEGetChar }
-
- function WEFeatureFlag (feature: Integer;
- action: Integer;
- hWE: WEHandle): Integer;
- var
- pWE: WEPtr;
- begin
- pWE := hWE^;
-
- { return current status }
- WEFeatureFlag := Integer(BTST(pWE^.flags, feature));
-
- { set new status if necessary }
- if (action = weBitClear) then
- BCLR(pWE^.flags, feature)
- else if (action = weBitSet) then
- BSET(pWE^.flags, feature);
-
- end; { WEFeatureFlag }
-
- function WEGetInfo (selector: OSType;
- info: Ptr;
- hWE: WEHandle): OSErr;
- begin
- WEGetInfo := _WEGetField(_WEMainSelectorTable, selector, info, hWE^);
- end; { WEGetInfo }
-
- function WESetInfo (selector: OSType;
- info: Ptr;
- hWE: WEHandle): OSErr;
- begin
- WESetInfo := _WESetField(_WEMainSelectorTable, selector, info, hWE^);
- end; { WESetInfo }
-
- end.